<template>
  <button
    class="count-down-btn"
    :class="[props.size]"
    :disabled="isDisabled"
    @click.prevent="send"
    :style="{ width: props.width }"
  >
    <span v-if="isLoading" class="loading">
      <slot name="icon">
        <loading-icon fill="#fff" :size="getIconSize" />
      </slot>
    </span>
    <span>
      {{ message }}
    </span>
  </button>
</template>

<script lang="ts" setup>
import { computed, ref } from 'vue';
import LoadingIcon from '@/base-ui/count-down-button/loading-icon.vue';

type checkInputType = () => Promise<boolean>;
type sendRequestType = () => Promise<any>;

enum sizeType {
  default = 'btn-default',
  small = 'btn-small',
  large = 'btn-large'
}

interface IProps {
  checkInput: checkInputType;
  sendRequest: sendRequestType;
  countSeconds: number;
  size?: sizeType;
  initTip: string;
  width?: string;
}

const props = withDefaults(defineProps<IProps>(), {
  countSeconds: 60,
  initTip: '发送验证码',
  size: sizeType.default,
  width: 'auto'
});

// 按钮中的文字提示
const message = ref(props.initTip);
// 按钮的禁用状态
const isDisabled = ref(false);
// 按钮的加载状态
const isLoading = ref(false);
// 倒计时的加载时间
const count = ref(props.countSeconds);

const getIconSize = computed(() => {
  switch (props.size) {
    case sizeType.small:
      return 12;
    case sizeType.large:
      return 16;
    default:
      return 14;
  }
});

async function send() {
  try {
    let res = await props.checkInput();
    if (!res) {
      console.warn('表单验证失败');
      return;
    }
    console.log('表单验证成功');
  } catch (err) {
    console.warn(err);
    return;
  }

  // 发送阶段
  console.log('发送邮件开始');
  isDisabled.value = true;
  isLoading.value = true;
  message.value = '发送中';

  // 等待发送结果
  try {
    const res = await props.sendRequest();
    console.log('异步请求结果', res);
    if (!res) {
      console.warn('异步请求发送失败');
      isLoading.value = false;
      isDisabled.value = false;
      message.value = props.initTip;
      return;
    }
    console.log('异步请求发送成功');
  } catch (err) {
    console.warn(err);
    isLoading.value = false;
    isDisabled.value = false;
    message.value = props.initTip;
    return;
  }

  // 收到发送结果
  console.log('发送结束');
  isLoading.value = false;
  // 进入倒计时
  console.log('开始等待');
  message.value = count.value + 's后重发';
  let timer = 0;
  await new Promise((resolve) => {
    timer = window.setInterval(() => {
      count.value--;
      message.value = `已发送${count.value}s`;
      if (count.value <= 0) {
        // 倒计时结束恢复初始状态并清除定时器
        resolve('res');
        message.value = '重新发送';
        clearInterval(timer);
        count.value = props.countSeconds;
      }
    }, 1000);
  });
  console.log('等待结束');
  isDisabled.value = false;
}
</script>

<style scoped lang="scss">
.btn-default {
  font-size: 14px;
}

.btn-small {
  font-size: 12px;
}

.btn-large {
  font-size: 16px;
}

.count-down-btn {
  height: 100%;
  padding: 0 12px;
  color: #fff;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  background-color: #409eff;
  cursor: pointer;
  transition: background-color 0.3s;
  outline: none;
  border: none;

  &:hover,
  &:focus {
    background-color: #66b1ff;
  }

  span {
    display: block;
  }

  .loading {
    margin-right: 4px;
    animation: loading 1s infinite linear;
  }

  &:active {
    background-color: #3375b9;
  }

  &:disabled {
    color: rgba(255, 255, 255, 0.5);
    background-color: #4f9bf5;
    cursor: not-allowed;
  }

  @keyframes loading {
    from {
      transform: rotate(0turn);
    }
    to {
      transform: rotate(1turn);
    }
  }
}
</style>
